<!--------------图库组件---------------->
<template>
    <div class="upload-panel">
        <el-upload
            ref="upload"
            v-model:file-list="imgList"
            action=""
            list-type="picture-card"
            :auto-upload="false"
            :class="['image-box', (imgList?.length > 0 && limit === 1) || imgList?.length >= limit ? 'limit' : '']"
            :multiple="multiple"
            @change="onAvatarBeforeUpload"
            accept="image/gif, image/jpg, image/jpeg, image/bmp, image/png, image/webp"
            :limit="limit"
            :disabled="$props.disabled"
        >
            <el-icon><Plus /></el-icon>
            <template #file="{ file }">
                <el-image :src="file.url" hide-on-click-modal :preview-src-list="[file.url]" style="width: 80px; height: 80px" preview-teleported />
                <div class="status">
                    <el-icon><Check></Check></el-icon>
                </div>
                <div class="icon-box" v-if="!$props.disabled">
                    <span class="icon">
                        <el-icon @click="handleImgRemove(file)"><Delete /></el-icon>
                    </span>
                </div>
            </template>
        </el-upload>
        <el-button type="primary" v-if="!$props.disabled" :icon="Picture" class="mt-3" @click="visible = true">图库</el-button>
        <el-button type="danger" :icon="Delete" class="mt-3" @click="handleImgRemoveAll" v-if="deleteAll">删除所有图片</el-button>
    </div>
    <el-dialog v-model="visible" width="50%" title="图库" @close="visible = false" append-to-body>
        <el-scrollbar height="400px">
            <el-tabs tab-position="left" v-loading="loading" @tab-click="changeCategory" v-model="activeName">
                <el-tab-pane v-for="item in categoryList" :label="item.name" :key="item.id" :name="item.id">
                    <div class="flex flex-wrap gap-3" v-if="imgHubList.length > 0">
                        <div
                            v-for="(imgItem, index) in imgHubList"
                            :key="imgItem.id"
                            class="img-hub-box overflow-hidden relative w-20 h-20 rounded cursor-pointer border-solid border border-slate-200 hover:border-sky-500"
                        >
                            <el-image
                                :src="imgItem.full_url"
                                fit="cover"
                                class="w-20 h-20"
                                :preview-src-list="[imgItem.full_url]"
                                preview-teleported
                                hide-on-click-modal
                            ></el-image>
                            <div class="select-box">
                                <el-checkbox
                                    label="选择"
                                    class="check"
                                    v-model="imgItem.isSelect"
                                    :value="imgItem.full_url"
                                    @change="changeCheck($event, imgItem.full_url)"
                                    :disabled="imgList.length >= limit && !imgItem.isSelect"
                                    v-if="multiple"
                                />
                                <el-radio
                                    v-else
                                    :value="imgItem.full_url"
                                    v-model="imgItem.isSelect"
                                    :label="imgItem.full_url"
                                    @change="singleChoice(imgItem.full_url, index)"
                                    >选择</el-radio
                                >
                            </div>
                        </div>
                    </div>
                    <el-empty v-else description="暂无数据" class="mt-16" />
                </el-tab-pane>
            </el-tabs>
        </el-scrollbar>
        <template #footer>
            <el-button @click="visible = false"
                ><el-icon class="mr-1"><CloseBold /></el-icon> 关闭</el-button
            >
        </template>
    </el-dialog>
</template>
<script setup>
import { ref, watch, nextTick } from 'vue'
import createAxios from '/@/utils/axios'
import { Plus, Delete, CloseBold, Picture, Check } from '@element-plus/icons-vue'
import { fileUpload } from '/@/api/common'
import { uuid } from '/@/utils/random'

let visible = ref(false) // 控制图库显示隐藏
const props = defineProps({
    modelValue: [Array, String],
    multiple: { type: Boolean, default: true }, // 是否多选
    limit: { type: Number, default: 1000 }, // 限制上传图片数量
    deleteAll: { type: Boolean, default: true }, // 是否显示删除所有图片按钮
    disabled: { type: Boolean, default: false } //禁用修改
})
let categoryList = ref([]) // 分类列表
let loading = ref(false) // 加载状态
let activeName = ref('') // 当前选中的分类
let imgHubList = ref([]) // 仓库图片列表
let imgList = ref([]) // 上传的图片列表
let checkList = ref([]) // 选中的图片列表
const upload = ref(null) // 上传组件实例

watch(
    () => props.modelValue,
    (val) => {
        if (!val) val = []
        if (typeof val === 'string') {
            val = val.split(',')
            nextTick(() => {
                emits('update:modelValue', val)
            })
        }
        imgList.value = val?.map((item) => {
            return { url: item, full_url: item }
        })
        checkList.value = val
    },
    {
        immediate: true,
    }
)
// 监听弹层显示隐藏
watch(
    () => visible.value,
    async (val) => {
        visible.value = val
        if (val) {
            loading.value = true
            activeName.value = ''
            await getImgCategory()
            await getImgHubList()
            loading.value = false
        }
    }
)

const emits = defineEmits(['update:modelValue'])
// 上传图片
const onAvatarBeforeUpload = (file) => {
    let fd = new FormData()
    fd.append('file', file.raw)
    fileUpload(fd, { uuid: uuid() }).then((res) => {
        if (res.code == 1) {
            file.url = res.data.url
            file.full_url = res.data.url
            file.status = 'success'
            emits('update:modelValue', getAllUrls(imgList.value))
        }
    })
}

//移除所选图片
const handleImgRemove = (file) => {
    // 因为对象是引用类型,更改imgList都会对原数组进行操作
    for (let i = 0; i < imgList.value.length; i++) {
        if (file.uid === imgList.value[i].uid) {
            imgList.value.splice(i, 1)
            checkList.value = checkList.value.filter((item) => item !== file.full_url)
            emits('update:modelValue', getAllUrls(imgList.value))
            break
        }
    }
}

// 移除所有图片
const handleImgRemoveAll = () => {
    imgList.value = []
    checkList.value = []
    emits('update:modelValue', getAllUrls(imgList.value))
}

// 获取所有图片地址
const getAllUrls = (imgList) => {
    let urlList = []
    imgList.forEach((item) => {
        urlList.push(item.full_url)
    })
    return urlList
}

//获取图片分类列表
const getImgCategory = async () => {
    const res = await createAxios({ url: '/admin/Category/index', method: 'get' })
    categoryList.value = res.data.list
    categoryList.value.unshift({ id: '', name: '最近上传' })
}

//获取图片列表
const getImgHubList = async (id) => {
    loading.value = true
    const res = await createAxios({ url: '/admin/routine.Attachment/index', method: 'get', params: { topic: id, limit: 50 } })
    imgHubList.value = res.data.list
    imgHubList.value.forEach((item) => {
        checkList.value.includes(item.full_url) ? (item.isSelect = true) : (item.isSelect = false)
    })
    loading.value = false
}

// 切换tab标签后根据分类ID获取图片列表
const changeCategory = (tab) => {
    getImgHubList(tab.paneName)
}

// 多选图片
const changeCheck = (val, imgUrl) => {
    if (val) {
        checkList.value.push(imgUrl)
        imgList.value.push({ url: imgUrl, full_url: imgUrl })
    } else {
        checkList.value = checkList.value.filter((item) => item !== imgUrl)
        for (let i = 0; i < imgList.value.length; i++) {
            if (imgList.value[i].full_url === imgUrl) {
                imgList.value.splice(i, 1)
                break
            }
        }
    }
    emits('update:modelValue', getAllUrls(imgList.value))
}

// 单选事件
const singleChoice = (val, index) => {
    imgHubList.value[index].isSelect = val
    imgList.value = [{ url: val, full_url: val }]
    emits('update:modelValue', getAllUrls(imgList.value))
    visible.value = false
}
</script>
<style scoped lang="scss">
.upload-panel {
    width: 100%;
    text-align: left;
    .image-box {
        width: 100%;
        :deep(.el-upload-list) {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
            gap: 10px;
            .el-upload-list__item {
                width: 80px;
                height: 80px;
                margin: 0px;
                position: relative;
                .status {
                    position: absolute;
                    width: 0;
                    height: 0;
                    border-right: 0px solid transparent;
                    border-left: 20px solid transparent;
                    border-top: 20px solid #67c23a;
                    right: 0px;
                    top: 0;
                    .el-icon {
                        color: #fff !important;
                        font-size: 12px;
                        position: absolute;
                        right: 0px;
                        top: -20px;
                    }
                }
                .icon-box {
                    position: absolute;
                    bottom: -20px;
                    left: 0;
                    height: 20px;
                    width: 100%;
                    z-index: 99;
                    background-color: rgba(0, 0, 0, 0.7);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    transition: all 0.3s;
                    .icon {
                        color: #fff;
                        font-size: 14px;
                        line-height: 14px;
                        margin: 0 5px;
                        cursor: pointer;
                    }
                }
                &:hover {
                    .icon-box {
                        bottom: 0px;
                    }
                }
            }
        }

        :deep(.el-upload--picture-card) {
            width: 80px;
            height: 80px;
            margin-right: 0px;
            order: -1;
        }
        &.limit {
            :deep(.el-upload--picture-card) {
                display: none;
            }
        }
        &.no-margin {
            :deep(.el-upload-list--picture-card) {
                height: 80px;
                display: block;
                .el-upload-list__item {
                    margin: 0px;
                }
            }
        }
    }
}
.img-hub-box {
    .select-box {
        position: absolute;
        bottom: 0px;
        right: 0;
        width: 100%;
        height: 20px;
        color: #fff;
        display: flex;
        padding-right: 3px;
        background-color: rgba(0, 0, 0, 0.35);
        justify-content: center;
        align-items: center;
        transition: all 0.3s;
        .el-checkbox {
            color: #fff !important;
            --el-checkbox-checked-text-color: #fff;
        }
        :deep(.el-radio__label) {
            color: #fff;
        }
    }
}
</style>
